QUIC传输机制的设计思想

在QUIC中,所有的传输数据包都与一个包级别的头部一起发送,其中包含数据包序列 号(packet sequence number,下面将会称之为数据包号(packet number)) 这些数据包号是单调递增的,并且在一次连接的生命周期中绝对不会 出现重复的值,这就使得重复检测显得没这么重要了。这一基本的设计决定消除了 传输与重传之间的歧义并降低了在QUIC中实现类似于TCP协议中丢包检测机制的复杂性。

每一个数据包都包含了好几个部分;我们会在下面概述对丢包检测与拥塞控制机制有着 重要联系的部分。

  • STREAM 帧包含了应用数据。加密握手的数据也作为STREAM数据发送,并使用了QUIC 下的可靠性机制。
  • ACK帧包含了确认信息。QUIC使用了一种基于NACK机制的方案,其中最大观测数据包 号( largest_observed packet number)被告知,而数据包序列号小于尚未看到 的最大观测数据包号的分组被报告为NACK范围。ACK帧还包括新确认的每个分组的接收时间戳。

QUIC与TCP之间的相关差异

有一些存在于QUIC与TCP协议之间值得注意的差异,这些差异直接导致了这两种协议采取 的丢包恢复机制的不同。我们将在下面简要地描述这些差异。

单调递增的序列号

TCP将发送方的传输序列号与接收方的传送序列号进行了合并,这将导致同样的数据将携带 同样的序列号,因此导致了“重传歧义(retransmission ambiguity)”的问题。而在QUIC中 则将这两者分了开来:QUIC使用了一个数据包传输号(即为序列号”sequence number”)用 于传输,任何将被传输到正在接收数据的那个应用的数据都将在一条或者多条流中完成,这 些流中的STREAM帧将包含用于确定发送顺序的流偏移值(stream offsets)。

QUIC的数据包序列号时严格递增的,其直接编码了传输的顺序。一个较高的QUIC序列号表 明这个数据包是较晚发送的,而较低的序列号则表明这个数据包是较早发送的。

这样的设计极大的简化了QUIC中的丢包检测机制。大多数TCP机制隐含地尝试基于TCP序列 号推断传输排序;这个任务实现难度不小的,特别是当TCP时间戳不可用时。

QUIC在需要重传时,将以一个新的数据包序列号来重发丢失的数据包,这消除了TCP中当收 到ACK信号时无法确定哪个数据包被确实收到的歧义。因此,可以进行更准确的RTT测量,简 单地检测虚假重传,并且可以仅基于序列号实现诸如快速重传(Fast Retransmit)等的机制。

No SACK Reneging

(注:Reneging的意思就是接收方有权把已经报给发送端SACK里的数据给丢了。)

QUIC中的ACK包含了与TCP中的SACK等价的信息,但是QUIC不允许任何以及被确认接 受的数据包被丢弃,这样不仅可以极大的简化了发送端与接收端的实现难度,还可以减少发送端的内存压力。

更大的NACK范围

相对于TCP的SACK范围为3,QUIC支持的NACK范围高达255。在高丢包率的网络环境下,这将加速数据的恢复。

延迟ACK包的显式校正

QUIC ACK显式的编码在接收分组和发送相应ACK之间在接收器处引起的延迟。这允 许ACK的接收器在估计路径RTT时调整接收器延迟,特别是延迟的ack计时器。 该机制还允许接收端测量并报告从OS的内核收到一个数据包时开始的延迟,这对于 在用户空间的QUIC接收器处理接收的分组之前,可能引起诸如上下文切换等待时间之类的延迟的接收器是有用的。